package com.happe.foodeasy.winter.conf.parser;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicReference;

/**
 * The super class that is used to run the task of parsing configuration files.
 * Created by wubin on 2016-05-19.
 */
public abstract class CommonParser<T> {
    private final AtomicReference<Future<T>> confResultAtomicReference = new AtomicReference<>();

    public T startParse() {
        while (true) {
            Future<T> f = confResultAtomicReference.get();
            if (f == null) {
                FutureTask<T> ft = new FutureTask<>(requireTaskCallable());
                f = confResultAtomicReference.getAndSet(ft);
                if (f == null) {
                    f = ft;
                    ft.run();
                }
            }
            try {
                T parseResultEntity = f.get();
                dealParseResultFurther(parseResultEntity);
                return parseResultEntity;
            } catch (InterruptedException e) {
                confResultAtomicReference.set(null);
            } catch (ExecutionException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * This is one hook method, subclass can override to deal with the
     * result of parsing.
     * @param result The result of parsing.
     */
    @SuppressWarnings("all")
    protected void dealParseResultFurther(T result) {
    }

    /**
     * The subclass implements this method to provide the task that should be run by this super
     * class.
     *
     * @return the task should be run.
     */
    protected abstract Callable<T> requireTaskCallable();
}
